package com.d3works.apps.bpm.service.init;

import com.d3works.apps.bpm.context.WkfContextHelper;
import com.d3works.apps.bpm.script.ContextFunctionMapper;
import com.d3works.apps.bpm.script.D3worksScriptEngineFactory;
import com.d3works.db.JPA;
import com.d3works.inject.Beans;
import java.util.ArrayList;
import java.util.List;
import org.camunda.bpm.application.impl.event.ProcessApplicationEventListenerPlugin;
import org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.camunda.bpm.engine.impl.variable.serializer.JavaObjectSerializer;
import org.camunda.bpm.engine.impl.variable.serializer.TypedValueSerializer;
import org.camunda.bpm.engine.impl.variable.serializer.jpa.EntityManagerSession;
import org.camunda.bpm.engine.impl.variable.serializer.jpa.JPAVariableSerializer;
import org.camunda.bpm.engine.variable.type.ValueType;
import org.camunda.spin.plugin.impl.SpinProcessEnginePlugin;

public class WkfProcessEngineConfigurationImpl extends StandaloneProcessEngineConfiguration {

  @Override
  protected void invokePreInit() {
    processEnginePlugins.add(new SpinProcessEnginePlugin());
    processEnginePlugins.add(new ProcessApplicationEventListenerPlugin());
    super.invokePreInit();
  }

  @Override
  protected void initJpa() {
    sessionFactories.put(
        EntityManagerSession.class,
        new WkfEntityManagerSessionFactory(JPA.em().getEntityManagerFactory(), false, false));
    JPAVariableSerializer jpaType =
        (JPAVariableSerializer) variableSerializers.getSerializerByName(JPAVariableSerializer.NAME);
    // Add JPA-type
    if (jpaType == null) {
      // We try adding the variable right after byte serializer, if available
      int serializableIndex =
          variableSerializers.getSerializerIndexByName(ValueType.BYTES.getName());
      if (serializableIndex > -1) {
        variableSerializers.addSerializer(new JPAVariableSerializer(), serializableIndex);
      } else {
        variableSerializers.addSerializer(new JPAVariableSerializer());
      }
    }
    variableSerializers.addSerializer(new JavaObjectSerializer());
    @SuppressWarnings("rawtypes")
    List<TypedValueSerializer> customPreVariableTypes = new ArrayList<TypedValueSerializer>();
    customPreVariableTypes.add(new JPAVariableSerializer());
    customPreVariableTypes.add(new JavaObjectSerializer());
    setCustomPreVariableSerializers(customPreVariableTypes);
  }

  @Override
  protected void initScripting() {
    super.initScripting();
    D3worksScriptEngineFactory factory = new D3worksScriptEngineFactory();
    scriptingEngines.getScriptEngineManager().registerEngineName("d3works", factory);
    scriptingEngines.addScriptEngineFactory(factory);
  }

  @Override
  protected void initBeans() {
    super.initBeans();
    beans.put("$ctx", Beans.get(WkfContextHelper.class));
  }

  @Override
  protected void initExpressionManager() {
    super.initExpressionManager();
    expressionManager.addFunctionMapper(new ContextFunctionMapper());
  }
}
